#include "lcd.h"
#include "timer.h"
#include "spi.h"

static uint16_t lcd_dev_xoffset = 0;
static uint16_t lcd_dev_yoffset = 0;

uint8_t SPI_WriteByte(uint8_t *TxData,uint16_t size)
{
    return HAL_SPI_Transmit(&hspi2,TxData,size,1000);
}

static void sunxi_lcd_cmd_write(uint8_t cmd)
{
	HAL_GPIO_WritePin(GPIOD,RS_Pin,GPIO_PIN_RESET);
    SPI_WriteByte(&cmd, 1);
}

void sunxi_lcd_data_write(uint8_t *data, uint32_t count)
{
	HAL_GPIO_WritePin(GPIOD,RS_Pin,GPIO_PIN_SET);
    SPI_WriteByte(data, count);
}

static void sunxi_lcd_para_write(uint8_t data)
{
	HAL_GPIO_WritePin(GPIOD,RS_Pin,GPIO_PIN_SET);
    SPI_WriteByte(&data, 1);
}

void lcd_init_320x480(lcd_display_rotation_t rotation)
{	
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);
	HAL_Delay(1500);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
	HAL_Delay(1500);
	
	HAL_GPIO_WritePin(GPIOB,PWM_Pin,GPIO_PIN_SET);
#if 1	
	// Positive Gamma Control
    sunxi_lcd_cmd_write( 0xe0);
    sunxi_lcd_para_write(0xf0);
    sunxi_lcd_para_write(0x3e);
    sunxi_lcd_para_write(0x30);
    sunxi_lcd_para_write(0x06);
    sunxi_lcd_para_write(0x0a);
    sunxi_lcd_para_write(0x03);
    sunxi_lcd_para_write(0x4d);
    sunxi_lcd_para_write(0x56);
    sunxi_lcd_para_write(0x3a);
    sunxi_lcd_para_write(0x06);
    sunxi_lcd_para_write(0x0f);
    sunxi_lcd_para_write(0x04);
    sunxi_lcd_para_write(0x18);
    sunxi_lcd_para_write(0x13);
    sunxi_lcd_para_write(0x00);

    // Negative Gamma Control
    sunxi_lcd_cmd_write(0xe1);
    sunxi_lcd_para_write(0x0f);
    sunxi_lcd_para_write(0x37);
    sunxi_lcd_para_write(0x31);
    sunxi_lcd_para_write(0x0b);
    sunxi_lcd_para_write(0x0d);
    sunxi_lcd_para_write(0x06);
    sunxi_lcd_para_write(0x4d);
    sunxi_lcd_para_write(0x34);
    sunxi_lcd_para_write(0x38);
    sunxi_lcd_para_write(0x06);
    sunxi_lcd_para_write(0x11);
    sunxi_lcd_para_write(0x01);
    sunxi_lcd_para_write(0x18);
    sunxi_lcd_para_write(0x13);
    sunxi_lcd_para_write(0x00);
    
    // Power Control 1
    sunxi_lcd_cmd_write(0xc0);
    sunxi_lcd_para_write(0x18);
    sunxi_lcd_para_write(0x17);

    // Power Control 2
    sunxi_lcd_cmd_write(0xc1);
    sunxi_lcd_para_write(0x41);

    // Power Control 3
    sunxi_lcd_cmd_write(0xc5);
    sunxi_lcd_para_write(0x00);

    // VCOM Control
    sunxi_lcd_cmd_write(0x1a);
    sunxi_lcd_para_write(0x80);

    // Memory Access Control
    sunxi_lcd_cmd_write(0x36);
    sunxi_lcd_para_write(0x48);

    // Pixel Interface Format
    sunxi_lcd_cmd_write(0x3a);
    sunxi_lcd_para_write(0x55);

    // Interface Mode Control
    sunxi_lcd_cmd_write(0xb0);
    sunxi_lcd_para_write(0x00);

    // Frame Rate Control
    sunxi_lcd_cmd_write(0xb1);
    sunxi_lcd_para_write(0xa0);

    // Display Inversion Control
    sunxi_lcd_cmd_write(0xb4);
    sunxi_lcd_para_write(0x02);

    // Display Function Control
    sunxi_lcd_cmd_write(0xb6);
    sunxi_lcd_para_write(0x02);
    sunxi_lcd_para_write(0x02);

    // Set image function
    sunxi_lcd_cmd_write(0xe9);
    sunxi_lcd_para_write(0x00);

    //Adjust Control 3
    sunxi_lcd_cmd_write(0xf7);
    sunxi_lcd_para_write(0xa9);
    sunxi_lcd_para_write(0x51);
    sunxi_lcd_para_write(0x2c);
    sunxi_lcd_para_write(0x82);

    // Write_memory_start
    sunxi_lcd_cmd_write(0x21);
    mdelay(120);
    //Exit Sleep
    sunxi_lcd_cmd_write(0x11);
    mdelay(120);

	lcd_dev_xoffset = 0;
	lcd_dev_yoffset = 0;
	switch (rotation)
	{
		case LCD_DISPLAY_ROTATION_0:
			sunxi_lcd_cmd_write(0x36);
			sunxi_lcd_para_write(0x48);
			break;
		case LCD_DISPLAY_ROTATION_90:
			sunxi_lcd_cmd_write(0x36);
			sunxi_lcd_para_write(0xe8);
			break;
		case LCD_DISPLAY_ROTATION_180:
			sunxi_lcd_cmd_write(0x36);
			sunxi_lcd_para_write(0x88);
			break;
		case LCD_DISPLAY_ROTATION_270:
			sunxi_lcd_cmd_write(0x36);
			sunxi_lcd_para_write(0x28);
			break;
		default:
			sunxi_lcd_cmd_write(0x36);
			sunxi_lcd_para_write(0x48);
			break;
	}

	// set_screen_size
    sunxi_lcd_cmd_write(0x2a);
    sunxi_lcd_para_write(0x00);
    sunxi_lcd_para_write(0x00);
    sunxi_lcd_para_write(0x01);
    sunxi_lcd_para_write(0x3f);

    sunxi_lcd_cmd_write(0x2b);
    sunxi_lcd_para_write(0x00);
    sunxi_lcd_para_write(0x00);
    sunxi_lcd_para_write(0x01);
    sunxi_lcd_para_write(0xdf);

	//Display on
    sunxi_lcd_cmd_write(0x29);
    mdelay(120);
#else
	sunxi_lcd_cmd_write(0x11);
	mdelay(120);
	sunxi_lcd_cmd_write(0x36);     // Memory Data Access Control MY,MX~~
	sunxi_lcd_para_write(0x48);   

	sunxi_lcd_cmd_write(0x3A);     
	//LCDDrvWriteReg(0x55);
	sunxi_lcd_para_write(0x55);   //LCDDrvWriteDat(0x66);

	sunxi_lcd_cmd_write(0xF0);     // Command Set Control
	sunxi_lcd_para_write(0xC3);   

	sunxi_lcd_cmd_write(0xF0);     
	sunxi_lcd_para_write(0x96);   

	sunxi_lcd_cmd_write(0xB4);     
	sunxi_lcd_para_write(0x01);   

	sunxi_lcd_cmd_write(0xB7);     
	sunxi_lcd_para_write(0xC6);   

	sunxi_lcd_cmd_write(0xC0);     
	sunxi_lcd_para_write(0x80);   
	sunxi_lcd_para_write(0x45);   

	sunxi_lcd_cmd_write(0xC1);     
	sunxi_lcd_para_write(0x13);   //18  //00

	sunxi_lcd_cmd_write(0xC2);     
	sunxi_lcd_para_write(0xA7);   

	sunxi_lcd_cmd_write(0xC5);     
	sunxi_lcd_para_write(0x0A);   

	sunxi_lcd_cmd_write(0xE8);     
	sunxi_lcd_para_write(0x40);
	sunxi_lcd_para_write(0x8A);
	sunxi_lcd_para_write(0x00);
	sunxi_lcd_para_write(0x00);
	sunxi_lcd_para_write(0x29);
	sunxi_lcd_para_write(0x19);
	sunxi_lcd_para_write(0xA5);
	sunxi_lcd_para_write(0x33);

	sunxi_lcd_cmd_write(0xE0);
	sunxi_lcd_para_write(0xD0);
	sunxi_lcd_para_write(0x08);
	sunxi_lcd_para_write(0x0F);
	sunxi_lcd_para_write(0x06);
	sunxi_lcd_para_write(0x06);
	sunxi_lcd_para_write(0x33);
	sunxi_lcd_para_write(0x30);
	sunxi_lcd_para_write(0x33);
	sunxi_lcd_para_write(0x47);
	sunxi_lcd_para_write(0x17);
	sunxi_lcd_para_write(0x13);
	sunxi_lcd_para_write(0x13);
	sunxi_lcd_para_write(0x2B);
	sunxi_lcd_para_write(0x31);

	sunxi_lcd_cmd_write(0xE1);
	sunxi_lcd_para_write(0xD0);
	sunxi_lcd_para_write(0x0A);
	sunxi_lcd_para_write(0x11);
	sunxi_lcd_para_write(0x0B);
	sunxi_lcd_para_write(0x09);
	sunxi_lcd_para_write(0x07);
	sunxi_lcd_para_write(0x2F);
	sunxi_lcd_para_write(0x33);
	sunxi_lcd_para_write(0x47);
	sunxi_lcd_para_write(0x38);
	sunxi_lcd_para_write(0x15);
	sunxi_lcd_para_write(0x16);
	sunxi_lcd_para_write(0x2C);
	sunxi_lcd_para_write(0x32);
	 

	sunxi_lcd_cmd_write(0xF0);     
	sunxi_lcd_para_write(0x3C);   

	sunxi_lcd_cmd_write(0xF0);     
	sunxi_lcd_para_write(0x69);   

	mdelay(120);

	sunxi_lcd_cmd_write(0x21);     

	sunxi_lcd_cmd_write(0x29);     
#endif	

}

void spi_display_set_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    sunxi_lcd_cmd_write(0x2a);
    sunxi_lcd_para_write((x1 >> 8) & 0xFF);
    sunxi_lcd_para_write(x1 & 0xFF);
    sunxi_lcd_para_write((x2 >> 8) & 0xFF);
    sunxi_lcd_para_write(x2 & 0xFF);
	

    sunxi_lcd_cmd_write(0x2b);
    sunxi_lcd_para_write((y1 >> 8) & 0xFF);
    sunxi_lcd_para_write(y1 & 0xFF);
    sunxi_lcd_para_write((y2 >> 8) & 0xFF);
    sunxi_lcd_para_write(y2 & 0xFF);

    sunxi_lcd_cmd_write(0x2C);

}

 void spi_display_show_color(uint16_t color_le)
{
    uint8_t color_be[2];
    color_be [0] = (uint8_t)((color_le & 0xff00) >> 8);
    color_be [1] = (uint8_t)(color_le & 0xff);

    spi_display_set_window(0, 0, LCD_SCREEN_WIDTH-1, LCD_SCREEN_HEIGHT-1);
	HAL_GPIO_WritePin(GPIOD,RS_Pin,GPIO_PIN_SET);
	
    for(uint16_t x = 0; x < LCD_SCREEN_WIDTH; x++)
        for(uint16_t y = 0; y < LCD_SCREEN_HEIGHT; y++)
            SPI_WriteByte(color_be, 2);
}


